package com.lam.dormitory.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lam.dormitory.util.ShiroUtils;
import com.lam.dormitory.entity.Role;
import com.lam.dormitory.entity.User;
import com.lam.dormitory.service.IRoleService;
import com.lam.dormitory.service.IUserRoleService;
import com.lam.dormitory.service.IUserService;
import com.lam.dormitory.util.CopyUtil;
import com.lam.dormitory.util.PasswordHelper;
import com.lam.dormitory.util.ResponseTemplate;
import com.lam.dormitory.vo.ChangePasswordVo;
import com.lam.dormitory.vo.UserDetailVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author lam
 * @since 2019-12-20
 */
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUserRoleService userRoleService;

    /**
     * 登陆
     * @param username
     * @param password
     * @param rememberMe
     * @return
     */
    @ApiOperation(value = "登陆", notes = "登陆")
    @PostMapping("/login")
    public ResponseTemplate login(String username, String password, @RequestParam(value = "rememberMe", defaultValue = "0") Integer rememberMe) {
        //进行身份验证
        try {
            //验证身份和登陆
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//            token.setRememberMe(1 == rememberMe);
            Subject subject = SecurityUtils.getSubject();
            //进行登录操作
            subject.login(token);
            User user = userService.selectUserByUsername(username);
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(User::getUserId, user.getUserId());
            Date date = new Date();
            user.setLastLoginTime(date);
            userService.update(user, wrapper);
        } catch (IncorrectCredentialsException e) {
            return new ResponseTemplate(500, "用户不存在或者密码错误");
        } catch (LockedAccountException e) {
            return new ResponseTemplate(500, "登录失败，该用户已被冻结");
        } catch (AuthenticationException e) {
            return new ResponseTemplate(500, "该用户不存在");
        } catch (Exception e) {
            return new ResponseTemplate(500, "未知异常");
        }
        return new ResponseTemplate(200, "登录成功", ShiroUtils.getSession().getId().toString());
    }

    /**
     * 登出
     *
     * @return
     */
    @ApiOperation(value = "登出", notes = "登出")
    @PostMapping("/getLogout")
    @RequiresUser
    public ResponseTemplate getLogout() {
        ShiroUtils.logout();
        return new ResponseTemplate(200, "登出成功");
    }

    /**
     * 添加用户
     * @param addUser
     * @return
     */
    @ApiOperation(value = "添加用户", notes = "添加用户")
//    @RequiresPermissions("user:add")
    @RequiresRoles(value = {"superadmin", "admin"}, logical = Logical.OR)
    @PostMapping("/add")
    public ResponseTemplate addUser(User addUser) {
        String username = addUser.getUsername();
        User user = userService.selectUserByUsername(username);
        if (null != user) {
            return new ResponseTemplate(500, "用户名已存在");
        }
        addUser.setStatus(1);
        Date date = new Date();
        addUser.setCreateTime(date);
        addUser.setUpdateTime(date);
        addUser.setLastLoginTime(date);
        PasswordHelper.encryptPassword(addUser);
        boolean result = userService.save(addUser);
        if (result) {
            return new ResponseTemplate(200, "用户添加成功");
        } else {
            return new ResponseTemplate(500, "用户添加失败");
        }
    }

    /**
     * 根据userId删除用户
     * @param userId
     * @return
     */
    @ApiOperation(value = "删除用户", notes = "根据userId删除用户")
    @RequiresRoles(value = {"superadmin", "admin"}, logical = Logical.OR)
//    @RequiresPermissions("user:delete")
    @PostMapping("/delete")
    public ResponseTemplate deleteUser(Long userId) {
        User user = new User();
        user.setUserId(userId);
        QueryWrapper<User> wrapper = new QueryWrapper<>(user);
        boolean result = userService.remove(wrapper);
        if (result) {
            return new ResponseTemplate(200, "用户删除成功");
        }
        return new ResponseTemplate(500, "用户删除失败");
    }

    /**
     * 编辑用户
     * @param user
     * @return
     */
    @ApiOperation(value = "编辑用户", notes = "编辑用户")
    @PostMapping("/edit")
//    @RequiresPermissions("role:edit")
    @RequiresRoles(value = {"admin", "superadmin"}, logical = Logical.OR)
    public ResponseTemplate editUser(User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUserId, user.getUserId());
        Date date = new Date();
        user.setUpdateTime(date);
        boolean update = userService.update(user, wrapper);
        if (update) {
            return new ResponseTemplate(200, "修改成功");
        }
        return new ResponseTemplate(500, "修改失败");

    }

    /**
     * 用户详情
     * @param userId
     * @return
     */
    @ApiOperation(value = "用户详情", notes = "可根据userId查询用户详情")
    @RequiresRoles(value = {"superadmin", "admin","student"}, logical = Logical.OR)
//    @RequiresPermissions("user:delete")
    @PostMapping("/detail")
    public ResponseTemplate userDetail(Long userId) {
        User user = new User();
        user.setUserId(userId);
        if (userId == null) {
            userId = ShiroUtils.getUserInfo().getUserId();
            user.setUserId(userId);
        }
        List<UserDetailVo> userList = userService.selectByUser(user);
//        QueryWrapper<User> wrapper = new QueryWrapper<>();
//        wrapper.lambda().eq(User::getUserId, userId);
//        List<User> userList = userService.list(wrapper);
        return new ResponseTemplate(200, "查询成功", userList);
    }

    /**
     * 用户列表数据
     * @param user
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiOperation(value = "用户列表数据", notes = "可按条件查询用户列表数据(userId,username) pageNum 默认为 1，pageSize默认为 0")
    @RequiresRoles(value = {"superadmin", "admin"}, logical = Logical.OR)
//    @RequiresPermissions("user:list")
    @PostMapping("/list")
    public ResponseTemplate selectUser(User user, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "0") Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<UserDetailVo> userList = userService.selectByUser(user);
        PageInfo<UserDetailVo> pageInfo = new PageInfo<>(userList);
        return new ResponseTemplate(200, "用户列表数据获取成功", userList, pageInfo.getTotal());
    }

    /**
     * 管理员角色修改密码
     */
    @ApiOperation(value = "管理员角色修改密码", notes = "根据userId修改密码")
    @RequiresRoles(value = {"superadmin", "admin"}, logical = Logical.OR)
//    @RequiresPermissions("user:assignRole")
    @PostMapping(value = "/adminChangePassword")
    public ResponseTemplate adminChangePassword(Long userId, String newPassword) {
        User user = new User();
        user.setUserId(userId);
        QueryWrapper<User> wrapper = new QueryWrapper<>(user);
        User formUser = userService.getOne(wrapper);

        User newUser = CopyUtil.getCopy(formUser, User.class);
        newUser.setPassword(newPassword);
        PasswordHelper.encryptPassword(newUser);
        QueryWrapper<User> wrapper1 = new QueryWrapper<>();
        wrapper1.lambda().eq(User::getUserId, userId);
        Date date = new Date();
        newUser.setUpdateTime(date);
        boolean result = userService.update(newUser, wrapper1);
        if (result) {
            return new ResponseTemplate(200, "修改密码成功");
        } else {
            return new ResponseTemplate(500, "修改密码失败");
        }
    }

    /**
     * 用户修改密码
     * @param changePasswordVo
     * @return
     */
    /*用户修改密码*/
    @ApiOperation(value = "用户修改密码", notes = "用户修改密码")
    @RequiresRoles(value = {"superadmin", "admin","student"}, logical = Logical.OR)
//    @RequiresPermissions("user:assignRole")
    @PostMapping(value = "/changePassword")
    public ResponseTemplate changePassword(ChangePasswordVo changePasswordVo) {
        if (!changePasswordVo.getNewPassword().equals(changePasswordVo.getConfirmNewPassword())) {
            return new ResponseTemplate(500, "两次密码输入不一致");
        }
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUserId, ShiroUtils.getUserInfo().getUserId());
        User loginUser = userService.getOne(wrapper);
        User newUser = CopyUtil.getCopy(loginUser, User.class);
        String oldPassword = loginUser.getPassword();

        newUser.setPassword(changePasswordVo.getOldPassword());
        newUser.setSalt(loginUser.getSalt());//需要把原密码的盐加进去
        String encryptPassword = PasswordHelper.getPassword(newUser);
        if (oldPassword.equals(encryptPassword)){
            newUser.setUserId(ShiroUtils.getUserInfo().getUserId());
            newUser.setPassword(changePasswordVo.getNewPassword());
            PasswordHelper.encryptPassword(newUser);
            Date date = new Date();
            newUser.setUpdateTime(date);
            QueryWrapper<User> wrapper1 = new QueryWrapper<>();
            wrapper1.lambda().eq(User::getUserId, ShiroUtils.getUserInfo().getUserId());
            boolean result = userService.update(newUser, wrapper1);
            if (result) {
                return new ResponseTemplate(200, "修改密码成功");
            } else {
                return new ResponseTemplate(500, "修改密码失败");
            }
        }
        return new ResponseTemplate(500,"您输入的旧密码有误");
    }

    /**
     * 分配角色
     */
    @ApiOperation(value = "分配角色", notes = "根据userId,roleIdStr分配角色")
    @RequiresRoles(value = {"superadmin", "admin"}, logical = Logical.OR)
//    @RequiresPermissions("user:assignRole")
    @PostMapping("/assign/role")
    public ResponseTemplate assignRole(Long userId, @RequestParam(value = "roleIds") List<Long> roleIds) {
        ResponseTemplate responseTemplate = userService.addAssignRole(userId, roleIds);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUserId, userId);
        User user = userService.getOne(wrapper);
        ShiroUtils.deleteCache(user.getUsername(), false);
        return responseTemplate;
    }

    /**
     * 分配角色列表查询
     */
    @ApiOperation(value = "分配角色列表查询", notes = "根据userId分配角色列表查询")
//    @RequiresPermissions("user:assignRole")
    @PostMapping("/assign/role/list")
    @RequiresRoles(value = {"superadmin", "admin"}, logical = Logical.OR)
    public ResponseTemplate assignRoleList(Long userId) {
        List<Role> roleList = roleService.selectRoleByUserId(userId);
        return new ResponseTemplate(200, "分配角色列表查询成功", roleList);
    }

    /**
     * 删除用户内的角色
     * @param userId
     * @param roleId
     * @return
     */
    @ApiOperation(value = "删除用户内的角色", notes = "根据userId,roleId删除用户内的角色")
    @PostMapping("/assign/role/delete")
//    @RequiresPermissions("role:assignPerms")
    @RequiresRoles(value = {"admin", "superadmin"}, logical = Logical.OR)
    public ResponseTemplate deleteRole(Long userId, Long roleId) {
        Map<String, Object> map = new HashMap<>();
        map.put("user_id", userId);
        map.put("role_id", roleId);
        boolean b = userRoleService.removeByMap(map);
        if (b) {
            return new ResponseTemplate(200, "删除成功");
        }
        return new ResponseTemplate(500, "删除失败");
    }
}
